package com.hbt.android.kotlin.learn

import java.lang.IllegalArgumentException


//  Kotlin      基本数据类型
//  Kotlin      的基本数值类型包括 Byte、Short、Int、Long、Float、Double 等。不同于 Java 的是，
//              字符不属于数值类型，是一个独立的数据类型。
//
//  类型	        位宽度
//  Double	    64
//  Float	    32
//  Long	    64
//  Int	        32
//  Short	    16
//  Byte	    8

// 定义常量与变量
// 可变变量定义：var 关键字
// var <标识符> : <类型> = <初始化值>
// 不可变变量定义：val 关键字，只能赋值一次的变量(类似Java中final修饰的变量)
// val <标识符> : <类型> = <初始化值>
// 常量与变量都可以没有初始化值,但是在引用前必须初始化
// 编译器支持自动类型判断,即声明时可以不指定类型,由编译器判断。


/**
 * 变量定义
 */
fun varDefined() {

    val number1: Int = 1 // 系统自动推断变量类型为Int
    val number2: Int  // 如果不在声明时初始化则必须提供变量类型，明确赋值
    var number = 100
    var bigNumber = 10000000000000
    var longNumber = 1L
    var byteNumber: Byte = 1
    var doubleNumber = 3.14159265453
    var floatNumber = 3.14159265453f


    // 字符串模板
    // $ 表示一个变量名或者变量值
    // $varName 表示变量值
    // ${varName.fun()} 表示变量的方法返回值:
    val string = "number is $number"
    val string1 = "${string.replace("is", "was")}, but now is $number"


    // NULL检查机制
    // Kotlin的空安全设计对于声明可为空的参数，在使用时要进行空判断处理，有两种处理方式，
    // 字段后加!!像Java一样抛出空异常，另一种字段后加?可不做处理返回值为 null或配合?:做空判断处理

    var age: String? = "21" // 后面加？表示可以为空
    val age1 = age!!.toInt() // 抛出空指针异常
    val age2 = age.toInt() // 不做处理返回null
    val age3 = age?.toInt() ?: -1 // age为返回-1
}


/**
 * 比较两个数字
 * Kotlin 中没有基础数据类型，只有封装的数字类型，你每定义的一个变量，其实 Kotlin 帮你封装了一个对象，这样可以保证不会出现空指针
 * 数字类型也一样，所以在比较两个数字的时候，就有比较数据大小和比较两个对象是否相同的区别了
 * 在 Kotlin 中，三个等号 === 表示比较对象地址，两个 == 表示比较两个值大小
 */
fun compare(a: Int, b: Int) {
    val c: Int = 10000
    println(c === c)

    // 创建了两个不同的对象
    val arg1: Int? = c
    val arg2: Int? = c

    println(arg1 === arg2)
    println(arg1 == arg2)
}


/**
 * 类型转换
 * 由于不同的表示方式，较小类型并不是较大类型的子类型，较小的类型不能隐式转换为较大的类型
 * 这意味着在不进行显式转换的情况下我们不能把 Byte 型值赋给一个 Int 变量。
 *
 * 每种数据类型都有下面的这些方法，可以转化为其它的类型：
 * toByte(): Byte
 * toShort(): Short
 * toInt(): Int
 * toLong(): Long
 * toFloat(): Float
 * toDouble(): Double
 * toChar(): Char
 */
fun typeParse() {
    // OK, 字面值是静态检测的
    val b: Byte = 1

    val i: Int = b.toInt()

    // 有些情况下也是可以使用自动类型转化的，前提是可以根据上下文环境推断出正确的数据类型而且数学操作符会做相应的重载
    // Long + Int => Long
    val l = 1L + 3

}


/**
 * 位操作符
 * 对于Int和Long类型，还有一系列的位操作符可以使用
 * shl(bits) – 左移位 (Java’s <<)
 * shr(bits) – 右移位 (Java’s >>)
 * ushr(bits) – 无符号右移位 (Java’s >>>)
 * and(bits) – 与
 * or(bits) – 或
 * xor(bits) – 异或
 * inv() – 反向
 */
fun bitManipulation() {

}


/**
 * Kotlin 中的 Char 不能直接和数字操作，Char 必需是单引号 ' 包含起来的。比如普通字符 '0'，'a'。
 * 字符字面值用单引号括起来: '1'。 特殊字符可以用反斜杠转义。
 * 支持这几个转义序列：\t、 \b、\n、\r、\'、\"、\\ 和 \$。 编码其他字符要用 Unicode 转义序列语法：'\uFF00'
 *
 */
fun char(c: Char): Int {
    if (c !in '1'..'9') {
        throw IllegalArgumentException("out of range")
    }
    // 当需要可空引用时，像数字、字符会被装箱。
    return c.toInt() - '0'.toInt()
}

/**
 * 布尔
 * 布尔用 Boolean 类型表示，它有两个值：true 和 false。
 * 若需要可空引用布尔会被装箱
 */
fun boolean() {
//    内置的布尔运算有：
//
//    || – 短路逻辑或
//    && – 短路逻辑与
//    ! - 逻辑非

}

/**
 * 数组
 * 数组用类 Array 实现，并且还有一个 size 属性及 get 和 set 方法，由于使用 [] 重载了 get 和 set 方法，所以我们可以通过下标很方便的获取或者设置数组对应位置的值。
 * 数组的创建两种方式：一种是使用函数arrayOf()；另外一种是使用工厂函数。
 */
fun array() {
    val array1 = arrayOf(1, 2, 3)

    val array2 = Array(3, { i -> (i * 2) } )

    // 读取数据内容
    println(array1[0])
    println(array2[0])


    // 除了类Array，还有ByteArray, ShortArray, IntArray，用来表示各个类型的数组，省去了装箱操作，因此效率更高，其用法同Array一样
    val x: IntArray = intArrayOf(1, 2, 3)
    x[0] = x[1] + x[2]
}

/**
 * 字符串
 * String 是不可变的。方括号 [] 语法可以很方便的获取字符串中的某个字符，也可以通过 for 循环来遍历
 */
fun character() {
    val text = """
        多行字符串1
        多行字符串2
    """.trimMargin() // 删除多余的空格

    for (c in text) {
        println(c)
    }
}

/**
 * 字符串模板
 * 字符串可以包含模板表达式 ，即一些小段代码，会求值并把结果合并到字符串中。
 * 模板表达式以美元符（$）开头，由一个简单的名字构成
 */
fun characterTemplate() {
    val str = "text"

    // 字符串可以包含模板表达式 ，即一些小段代码，会求值并把结果合并到字符串中。 模板表达式以美元符（$）开头，由一个简单的名字构成
    val str1 = "content is $str"


    // 或者用花括号扩起来的任意表达式
    val str2 = "content length is ${str.length}"

    // 原生字符串和转义字符串内部都支持模板。 如果你需要在原生字符串中表示字面值 $ 字符（它不支持反斜杠转义）
    val price = """
    ${'$'}9.99
    """
    // 求值结果为 $9.99
    println(price)

}

fun main() {




}
